今天我們來看正規表達式,在談到為什麼需要多學這個之前,先來看個範例。
假設需要判斷輸入字串是否含有"apple":
var text="A apple a day keeps the doctor away";
function hasApple(val){
hasStr = val.indexOf("apple");
if(hasStr === -1) return false;
return true;
}
hasApple(text);//true
看起來很簡單,對吧!但如果今天要判斷的不只一個的話呢?
只能不段增加變數和判斷式長度嗎?這聽起來就是個寫"糙 code "的開始。
(想知道什麼是 "糙 code " 可以參考這個系列喔 可不可以不要寫糙 code)
那麼該怎麼作呢?很簡單, JS 有提供給我們正規表達式,可以這樣寫:
var text="A apple a day keeps the doctor away";
function hasApple(val){
return /apple/.test(text)
}
hasApple(text);//true
是不是比上面的例子乾淨許多了呢!
既然這樣,話不多說我們趕緊來看到底怎麼用吧。
RegExp 實例const pattern = /apple/;
const otherPattern = new RegExp("test");
兩種方式都能建立出相同的正規表達式,但如果在一開始就知道了正規表達式的內容,會一般會比較推薦用實值的方式建立,建構式方式比較用於程式執行階段時,動態透過字串建立。
--《忍者 JavaScript 開發技巧探祕》,第十章
接下來會列出常見的語法以及與之相關的方法,可能會讓你認為難以理解,但我會盡我所能的用範例講解。
首先我們要知道正規表達式都會包含兩個 / ,千萬不要跟 \ 搞混,他是有特殊用法的!
| 語法 | 說明 |
|---|---|
| /apple/ | 含有 apple 的字串 |
| /./ | 含有任意字元的字串 |
| /apple./ | 含有apple 後面接任意字元的字串 |
範例:
var text = "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!";
/apple/.test(text);//true
text.match(/./);//["A", index: 0, input: "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!", groups: undefined]
text.replace(/./,"hi")
//"hi apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!"
這邊我們可以看到
test 是回傳字串內"是否"含有正規表達式指定的字元。match 會根據 正規表達式回傳符合字串的陣列。replace 會根據 正規表達式取代符合字串。| 語法 | 說明 |
|---|---|
| /apple/i | 不區分英文大小寫 |
| /apple/g | 全域匹配,只要符合就會回傳 |
| m | 多行匹配 |
| y | 進行黏性匹配(sticky matching),只會對最後一次符合處之後進行匹配 ,需要配合設定 lastIndex |
| u | 對 unicode 數值作跳脫 |
範例:
var text = "A apple a day keeps the doctor away.I have pen , I have apple.Uh ! ApplePen!!";
/apple/.test(text);//true
text.match(/apple/g);//["apple", "apple"]
text.match(/apple/ig);//["apple", "apple", "Apple"]
text.replace(/apple/ig,"hi");//"A hi a day keeps the doctor away.I have pen , I have hi.Uh ! hiPen!!"
y這邊我特別拉出來說明,因為看了官網文件還是不太懂,搜尋很久才得到解答:
var str = "I have apple";
//0123456789
var regx = /apple/y;
regx.lastIndex = 7;
regx.test(str);//true
regx.test(str);//false
y 會根據你設置的 lastIndex 位置開始匹配,不匹配則回傳否,不會在往下尋找,
且 lastIndex 重製為 0 。
通常使用於避免前綴字串影響正規表達式時。
| 語法 | 說明 |
|---|---|
| ^ | 字串開頭必須符合條件字元 |
| $ | 字串結尾必須符合條件字元 |
| * | 字元可以出現0次以上 |
| ? | 字元可以出現1次或0次 |
| + | 字元至少出現1次 |
| {} | 指定字元重複出現次數 |
| {1,} | 指定字元重複出現1次以上 |
| {,3} | 指定字元重複出現3次以下 |
/^test/.test("est test");//false
/test$/.test("est test");//true
/t+est/.test("est");//false
/t?est/.test("est");//true
/t*est/.test("ttttest");//true
/t{,3}est/.test("ttttest");//false
| 語法 | 說明 |
|---|---|
| [] | 字串若含有 [xxx] 裡面字元則匹配 |
| [^] | 字串若不含有 [^xxx] 裡面字元則匹配 |
| [0-9] | 字串若含有 數字0到9 字元則匹配 |
| [a-z] | 字串若含有 a到z 字元則匹配 |
/^[a-z]/.test("est test");//true
/[0-9]$/.test("est test");//false
/^[^a-z]/.test("est test");//false
/[0-9]/.test("1est test");//true
我們前面有提到過 \ 會有特殊用途,這邊就是囉!
| 語法 | 說明 |
|---|---|
| \d | 任何數字字元,等於[0-9] |
| \D | 任何非數字字元,等於[^0-9] |
| \w | 任何數字字元字母底線,等於 [A-Za-z0-9_] |
| \W | 任何非數字字元字母底線,等於 [^A-Za-z0-9_] |
| \s | 任何空白字元(空格、Tab及換頁),等於 [ \f\n\r\t\v] |
| \S | 空白字元之外的其他字元,等於 [^ \f\n\r\t\v] |
//檢查西元格式
/^\d{4}-\d{2}-\d{2}$/.test("1992-12-22");//true
以上就是常見的正規別達式語法,老實說自己也很少用到這麼多,多半是想到時候才去查一下用法。
這邊跟各位分享一個 橫線區個的字串轉為駝峰式的程式:
var text = "has-a-text";
function upper (match,p1){
return p1.toUpperCase()
}
text = text.replace(/-(\w)/g,upper);//"hasAText"
參考資料:
忍者 JavaScript 開發技巧探祕
What does regex' flag 'y' do?
Javascript Regular Expressions , 表示法
MDN-正規表達式
[實用] 用 Regular Expression 做字串比對